package com.yi.wood.web.service.impl;

import com.yi.wood.base.Result;
import com.yi.wood.base.ResultCodeEnum;
import com.yi.wood.entity.AppUser;
import com.yi.wood.sequence.Snowflake;
import com.yi.wood.service.exception.BusinessException;
import com.yi.wood.service.impl.AbstractAppUserService;
import com.yi.wood.service.po.AppUserCachePo;
import com.yi.wood.utils.StringTokenUtil;
import com.yi.wood.web.ctrl.dto.AppUserDto;
import com.yi.wood.web.service.AppUserProService;
import com.yi.wood.web.util.UserCacheUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author MoYi
 * create date 2019/4/14 11:49
 */
@Service("appUserProService")
public class AppUserProServiceImpl extends AbstractAppUserService implements AppUserProService {

    @Resource
    private Snowflake snowflake;

    @Resource
    private UserCacheUtil userCacheUtil;

    @Override
    public AppUserCachePo appUserLogin(String userName, String password, String code) {
        // TODO 校验验证码
        AppUser appUser = appUserDao.findAppUserByUserName(userName);
        if (Objects.isNull(appUser)){
            throw new BusinessException(new Result(ResultCodeEnum.AUTH_FAILED, null));
        }

        AppUserCachePo appUserCachePo;

        if (appUser.getPassword().equals(password)){
            String id = StringTokenUtil.prefix(snowflake.nextId());
            String token = StringTokenUtil.getToken(userName, id);
            appUserCachePo = toAppUserCachePo(appUser);
            appUserCachePo.setToken(token);
            userCacheUtil.cacheUser(id, appUserCachePo);
            // 更新用户信息
            appUser.setLastModifyTime(new Date());
            updateData(appUser);
        }else {
            throw new BusinessException(new Result(ResultCodeEnum.AUTH_FAILED, null));
        }

        return appUserCachePo;
    }

    @Override
    public Page<AppUserDto> pageAppUserList(String userName, String phone, Integer pageNum, Integer pageSize) {
        Sort sort = new Sort(Sort.Direction.DESC,"createTime");
        Pageable pageable = PageRequest.of((pageNum - 1), pageSize, sort);

        Page<AppUser> page = appUserDao.findAll(new Specification<AppUser>() {
            List<Predicate> listPre = new ArrayList<>();
            @Override
            @Nullable
            public Predicate toPredicate(Root<AppUser> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                Predicate[] pre = new Predicate[listPre.size()];

                criteriaQuery.where(listPre.toArray(pre));
                return criteriaBuilder.and(pre);
            }
        }, pageable);
        return new PageImpl<>(toAppUserDtos(page.getContent()), pageable, page.getTotalElements());
    }

    @Override
    public AppUserDto getUserParentUserInfo(Long userId) {
        AppUser appUser = appUserDao.findAppUserById(userId);
        Assert.notNull(appUser,"用户不能为空");
        Assert.notNull(appUser.getParentId(), "用户不能没有上级");
        appUser = appUserDao.findAppUserById(appUser.getParentId());
        Assert.notNull(appUser,"上级用户不能为空");
        return toAppUserDto(appUser);
    }

    @Override
    public List<AppUserDto> getUserNextNodeUserInfo(Long userId) {
        List<AppUser> appUserList = appUserDao.findAppUserByParentId(userId);
        return toAppUserDtos(appUserList);
    }

    private List<AppUserDto> toAppUserDtos(List<AppUser> list) {
        List<AppUserDto> dtos = new ArrayList<>(list.size());
        list.forEach(user -> {
            AppUserDto dto = new AppUserDto();
            BeanUtils.copyProperties(user, dto);
            dtos.add(dto);
        });
        return dtos;
    }

    private AppUserDto toAppUserDto(AppUser appUser){
        AppUserDto dto = new AppUserDto();
        BeanUtils.copyProperties(appUser, dto);
        return dto;
    }

    private AppUserCachePo toAppUserCachePo(AppUser appUser){
        AppUserCachePo appUserCachePo = new AppUserCachePo();
        appUserCachePo.setUserName(appUser.getUserName());
        appUserCachePo.setEmail(appUser.getEmail());
        appUserCachePo.setLastLoginIp(appUser.getLastLoginIp());
        appUserCachePo.setPhone(appUser.getPhone());
        return appUserCachePo;
    }
}
